package cn.iocoder.yudao.module.student.service.studentEntryInfo;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.student.controller.app.studentEntryInfo.vo.*;
import cn.iocoder.yudao.module.student.dal.dataobject.studentEntryInfo.StudentEntryInfoDO;
import cn.iocoder.yudao.module.student.dal.dataobject.studentEntryInfo.WebEntryStudentDO;
import cn.iocoder.yudao.module.student.dal.mysql.studentEntryInfo.StudentEntryInfoMapper;
import cn.iocoder.yudao.module.student.dal.mysql.studentEntryInfo.WebEntryStudentMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.student.enums.ErrorCodeConstants.*;

/**
 * 项目报名信息 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
@Slf4j
public class StudentEntryInfoServiceImpl implements StudentEntryInfoService {

    @Resource
    private StudentEntryInfoMapper studentEntryInfoMapper;
    @Resource
    private WebEntryStudentMapper webEntryStudentMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createPraxisEntryInfo(@Valid StudentEntryInfoBaseVO createReqVO) {
        StudentEntryInfoDO studentEntryInfoDO=new StudentEntryInfoDO();
        BeanUtils.copyProperties(createReqVO,studentEntryInfoDO);
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        log.info("createPraxisEntryInfo--student:"+loginUserId+"--"+createReqVO.getStudentId());
        if(!loginUserId.equals(createReqVO.getStudentId()) ){
            throw exception(PRAXIS_ENTRY_ALREADY );
        }
        List<WebEntryStudentBaseVO> stuList = createReqVO.getStuList();
        for (WebEntryStudentBaseVO s : stuList) {
            s.setProjectId(createReqVO.getProjectId());
            Long aLong = webEntryStudentMapper.selectCount(new QueryWrapper<WebEntryStudentDO>().eq("project_id", createReqVO.getProjectId())
                    .eq("student_id", s.getStudentId()));
            if(null!=aLong && aLong>0){
                ErrorCode PRAXIS_ENTRY_ALREADY = new ErrorCode(1004050016, s.getStudentName()+"-已报名该项目");
                throw exception(PRAXIS_ENTRY_ALREADY );
            }
        }

        studentEntryInfoDO.setStudentId(loginUserId);
        Date date=new Date();
        studentEntryInfoDO.setCreateTime(date);
        studentEntryInfoDO.setUpdateTime(date);
        studentEntryInfoDO.setEntryTime(date);
        studentEntryInfoDO.setEntryStatus(2);
        if(null==studentEntryInfoDO.getStudentId()){
            WebEntryStudentBaseVO s = stuList.stream().filter(m -> (1 == m.getJobType())).findFirst().orElse(null);
            if(null!=s){
                studentEntryInfoDO.setStudentId(s.getStudentId());
            }
        }
        studentEntryInfoDO.setSourceAgent(ServletUtils.getSourceAgent());
        studentEntryInfoDO.setTeamNum(stuList.size());
        studentEntryInfoMapper.insert(studentEntryInfoDO);
        saveWebEntryStudent(1,stuList,studentEntryInfoDO.getId(),loginUserId,studentEntryInfoDO.getProjectId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePraxisEntryInfo(@Valid StudentEntryInfoBaseVO updateReqVO) {
        StudentEntryInfoDO entryInfoDO = studentEntryInfoMapper.selectById(updateReqVO.getId());
        if(entryInfoDO==null || entryInfoDO.getScheduleType()!=1){
            throw exception(PRAXIS_ENTRY_NOT_EXISTS );
        }
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        if(!entryInfoDO.getStudentId().equals(loginUserId)){
            throw exception(PRAXIS_ENTRY_NO_AUTH );
        }
        StudentEntryInfoDO studentEntryInfoDO=new StudentEntryInfoDO();
        BeanUtils.copyProperties(updateReqVO,studentEntryInfoDO);
        studentEntryInfoDO.setStudentId(loginUserId);
        Date date=new Date();
        if(null==studentEntryInfoDO.getEntryStatus() ){
            studentEntryInfoDO.setEntryStatus(2);
        }
        studentEntryInfoDO.setEntryTime(date);
        studentEntryInfoDO.setUpdateTime(date);
        List<WebEntryStudentBaseVO> stuList = updateReqVO.getStuList();
        studentEntryInfoDO.setTeamNum(stuList.size());
        studentEntryInfoDO.setEntryTime(date);
        studentEntryInfoDO.setSourceAgent(ServletUtils.getSourceAgent());
        studentEntryInfoMapper.updateById(studentEntryInfoDO);
        saveWebEntryStudent(2,stuList,studentEntryInfoDO.getId(),loginUserId,studentEntryInfoDO.getProjectId());
    }

    @Override
    public void uploadAnnex( StudentEntryInfoUpdateVO updateReqVO) {
        Long total = studentEntryInfoMapper.getScheduleByEntryId(updateReqVO.getId(),1);
        if(null==total || 0==total){
            throw exception(PRAXIS_SCHEDULE_UPLOAD_END );
        }
        StudentEntryInfoDO studentEntryInfoDO=new StudentEntryInfoDO();
        studentEntryInfoDO.setId(updateReqVO.getId());
        studentEntryInfoDO.setEntryStatus(2);
        studentEntryInfoDO.setEntryTime(new Date());
        studentEntryInfoDO.setAnnexName(updateReqVO.getAnnexName());
        studentEntryInfoDO.setAnnexUrl(updateReqVO.getAnnexUrl());
        studentEntryInfoMapper.updateById(studentEntryInfoDO);
    }

    /**
     *
     * @param type 1:添加 2：修改
     * @param stuList
     * @param entryId
     * @param loginUserId
     * @param projectId
     */
    public void saveWebEntryStudent(int type, List<WebEntryStudentBaseVO> stuList,Long entryId,Long loginUserId,Long projectId){
        if(2==type){
            webEntryStudentMapper.delete(new QueryWrapper<WebEntryStudentDO>().eq("entry_id",entryId));
        }
        String loginUserName = SecurityFrameworkUtils.getLoginUser().getUsername();
        if(1==stuList.size()){
            WebEntryStudentBaseVO webEntryStudentBaseVO=stuList.get(0);
            WebEntryStudentDO studentDO=new WebEntryStudentDO();
            studentDO.setId(null);
            BeanUtils.copyProperties(webEntryStudentBaseVO,studentDO);
            studentDO.setEntryId(entryId);
            studentDO.setJobType(1);
            studentDO.setCreator(loginUserName);
            studentDO.setCreateTime(new Date());
            studentDO.setStudentId(loginUserId);
            studentDO.setProjectId(projectId);
            webEntryStudentMapper.insert(studentDO);
        }else{
            List<WebEntryStudentDO> list=new ArrayList<>();
            stuList.stream().forEach(m->{
                WebEntryStudentDO studentDO=new WebEntryStudentDO();
                BeanUtils.copyProperties(m,studentDO);
                studentDO.setId(null);
                studentDO.setEntryId(entryId);
                studentDO.setCreateTime(new Date());
                studentDO.setCreator(loginUserName);
                studentDO.setProjectId(projectId);
                list.add(studentDO);
            });
            webEntryStudentMapper.insertBatch(list);
        }
    }

    @Override
    public void deletePraxisEntryInfo(Long id) {
        StudentEntryInfoDO studentEntryInfoDO = studentEntryInfoMapper.selectById(id);
        if(null==studentEntryInfoDO){
            throw exception(PRAXIS_ENTRY_NOT_EXISTS );
        }
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        if(!loginUserId.equals(studentEntryInfoDO.getStudentId())){
            throw exception(PRAXIS_ENTRY_NO_AUTH );
        }
        Long total = studentEntryInfoMapper.getScheduleByEntryId(id,0);
        if(null==total || 0==total){
            throw exception(PRAXIS_SCHEDULE_END );
        }
        webEntryStudentMapper.update(Wrappers.<WebEntryStudentDO>lambdaUpdate().set(WebEntryStudentDO::getDeleted,1).
                eq(WebEntryStudentDO::getEntryId,id));
        studentEntryInfoMapper.delete(new QueryWrapper<StudentEntryInfoDO>()
                .eq("project_id",studentEntryInfoDO.getProjectId())
                .eq("student_id",studentEntryInfoDO.getStudentId()));
    }

    @Override
    public StudentEntryInfoRespVO getPraxisEntryInfo(Long id) {
        StudentEntryInfoRespVO respVO=studentEntryInfoMapper.getStudentEntryInfo(id);
        if(null!=respVO){
            List<WebEntryStudentDO> list = webEntryStudentMapper.selectList(new QueryWrapper<WebEntryStudentDO>().eq("entry_id", respVO.getFirstEntryId()).orderByAsc("id"));
            List<WebEntryStudentBaseVO> rList=new ArrayList<>();
            list.stream().forEach(m->{
                WebEntryStudentBaseVO studentDO=new WebEntryStudentBaseVO();
                BeanUtils.copyProperties(m,studentDO);
                rList.add(studentDO);
            });
            respVO.setStuList(rList);
        }
        return respVO;
    }

    @Override
    public StudentEntryChosenVO getResultInfo(Long id) {
        return studentEntryInfoMapper.getEntryChosenInfo(id);
    }

    @Override
    public StudentResultVO getResultInfoByProjectId(Long projectId) {
        return studentEntryInfoMapper.getResultInfoByProjectId(projectId);
    }

    @Override
    public PageResult<StudentEntryInfoRespVO> getPraxisEntryInfoPage(StudentEntryInfoPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<StudentEntryInfoRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        if(null!=pageReqVO.getStudentId()){
            params.put("studentId",pageReqVO.getStudentId());
        }
        params.put("queryType",1);
        mpPage.setRecords(studentEntryInfoMapper.getPraxisEntryInfoPage(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }
    @Override
    public Integer getCheckStatus(Long projectId){
        Map<String, Object> params = new HashMap<>();
        params.put("studentId", SecurityFrameworkUtils.getLoginUserId());
        params.put("projectId", projectId);
        params.put("queryType", 2);
        List<StudentEntryInfoRespVO> list = studentEntryInfoMapper.getPraxisEntryInfoPage(null, params);
        if(CollectionUtils.isNotEmpty(list)){
            Integer checkStatus = NumberUtils.getInteger(list.get(0).getCheckStatus(),0) ;
            return checkStatus;
        }
        return 0;
    }


    @Override
    public PageResult<StudentEntryInfoRespVO> getSchedulePage(StudentEntryInfoPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<StudentEntryInfoRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        if(null!=pageReqVO.getStudentId()){
            params.put("studentId",pageReqVO.getStudentId());
        }
        if(null!=pageReqVO.getScheduleType()){
            params.put("scheduleType",pageReqVO.getScheduleType());
        }
        if(null!=pageReqVO.getCheckStatus()){
            params.put("checkStatus",pageReqVO.getCheckStatus());
        }
        if(null!=pageReqVO.getEntryStatus()){
            params.put("entryStatus",pageReqVO.getEntryStatus());
        }
        if(StringUtils.isNotBlank(pageReqVO.getTitle())){
            params.put("title",pageReqVO.getTitle());
        }
        mpPage.setRecords(studentEntryInfoMapper.getSchedulePage(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }
    @Override
    public Long getPraxisStudentNum(Long projectId, Long studentId) {
        Long num = studentEntryInfoMapper.getPraxisStudentNum(projectId, studentId);
        return null==num ? 0 : num;
    }
}
